<?php


namespace App\Utils\JWT;

use App\Utils\JWT\Exceptions\TokenInvalidException;

/**
 * Class Token
 * @package App\Utils\JWT
 * jwt的简易实现
 */
class Token
{

    public Header $header;

    public Payload $payload;

    /**
     * @var string 原始的token string
     */
    public string $rawToken;

    /**
     * 生成一个新的token
     * @param string|array|Payload $payload
     * @return self
     */
    public static function make($payload)
    {
        $ins = new self();
        $ins->header = new Header();
        if ($payload instanceof Payload){
            $ins->payload = $payload;
        }elseif(is_array($payload)){
            $ins->payload = new Payload($payload);
        }else{
            $ins->payload = new Payload(Signer::decode($payload));
        }
        return $ins;
    }

    /**
     * @param string $rawToken 字符串
     * @return self
     * @throws TokenInvalidException
     */
    public static function parseRawToken(string $rawToken)
    {
        $arr = explode('.',$rawToken,3);
        if (count($arr) != 3){
            throw new TokenInvalidException('token error');
        }
        $head = Header::parse($arr[0]);
        if (!Signer::verifySign($arr[0] . '.' . $arr[1], $arr[2], $head->alg)){
            throw new TokenInvalidException('sign not match');
        }
        $ins = new self();
        $payload = Payload::parse($arr[1]);
//        if ($payload->exp < time()){
//            throw new TokenInvalidException('token expired');
//        }
        $ins->header = $head;
        $ins->payload = $payload;
        $ins->rawToken = $rawToken;
        return $ins;
    }


    public function toString()
    {
        $hs = $this->header->toString() ;
        $ps = $this->payload->toString();
        $sign = Signer::makeSign($hs. '.' . $ps, $this->header->alg);
        return "{$hs}.{$ps}.{$sign}";
    }
}
